'use strict';
// based on the original work of
// https://github.com/karlsander/spotify-url-info
const deezerApi = require('deezer-request2');
const getAlbumTracks = require('./getAlbumTracks');
const { parse } = require('himalaya');
const axios = require('axios');
const signale = require('signale');

const sanityCheck = (data) => {
  if (!data || !data.type || !data.name) {
    return Promise.reject(new Error("Data doesn't seem to be of the right shape to parse"));
  }
  if (data.type != 'track' && data.type != 'album' && data.type != 'playlist' && data.type != 'artist') {
    return Promise.reject(new Error('Not an album, artist, track or playlist. Only these types can be parsed'));
  }
  return Promise.resolve(data);
};

const getData = (type, id) => {
  const embedURL = 'https://embed.spotify.com/?uri=spotify:' + type + ':' + id;

  return axios
    .get(embedURL)
    .then((res) => parse(res.data))
    .then(
      (data) =>
        data
          .filter((e) => e.tagName === 'html')[0]
          .children.filter((e) => e.tagName === 'body')[0]
          .children.filter(
            (e) => e.tagName === 'script' && e.attributes.findIndex((a) => a.value === 'resource') !== -1
          )[0].children[0].content
    )
    .then((encodedData) => JSON.parse(decodeURIComponent(encodedData)))
    .then(sanityCheck);
};

const getPreview = (url) => {
  return getData(url).then(parseIntoPreview);
};

const parseIntoPreview = (data) => {
  const firstTrack = getFirstTrack(data);
  const images = data.type === 'track' ? data.album.images : data.images;
  return Promise.resolve({
    title: data.name,
    type: data.type,
    track: firstTrack.name,
    artist: firstTrack.artists.map((a) => a.name).join(' & '),
    image: images.reduce((a, b) => (a.width > b.width ? a : b)).url,
    audio: firstTrack.preview_url,
    link: data.external_urls.spotify,
    embed: 'https://embed.spotify.com/?uri=' + data.uri,
  });
};

const spotifyTrack2Deezer = async (isrc) => {
  const { data } = await axios.get('https://api.deezer.com/track/isrc:' + isrc);
  if (data.error) {
    throw `Unavailable to find any match for #${isrc}!`;
  }
  const trackInfo = await deezerApi.getTrackInfo(data.id);
  return trackInfo.data.results;
};

const spotify2Deezer = async (info) => {
  const data = await getData(info.type, info.id);
  switch (data.type) {
    case 'track':
      return await spotifyTrack2Deezer(data.external_ids.isrc);
    case 'album':
      try {
        let legacyApiAlbum = await axios.get('https://api.deezer.com/album/upc:' + data.external_ids.upc);
        let albumInfo = await deezerApi.getAlbumTrackInfo(legacyApiAlbum.data.id);
        info.title = albumInfo.data.results.ALB_TITLE;
        info.id = albumInfo.data.results.ALB_ID;
        info.data = albumInfo.data.results;

        info.tracks = await getAlbumTracks(info.id);
        return info;
      } catch (e) {
        throw { error: 'ALbum #' + info.id, message: 'This album is not available on deezer!' };
      }
    case 'playlist':
      // playlist tracks are limited to 100
      signale.pending('Fetching spotify playlist. This might take a while.');
      const playlist_tracks = await Promise.all(
        data.tracks.items.map(async (item) => {
          try {
            return await spotifyTrack2Deezer(item.track.external_ids.isrc);
          } catch (e) {
            return {};
          }
        })
      );

      info.title = data.name;
      info.data = data;
      info.tracks = playlist_tracks.filter((item) => item.SNG_ID);
      return info;
    case 'artist':
      // artist tracks are limited to 10
      signale.pending("Fetching spotify artist tracks. Shouldn't take long.");
      const artist_tracks = await Promise.all(
        data.tracks.map(async (item) => {
          try {
            return await spotifyTrack2Deezer(item.external_ids.isrc);
          } catch (e) {
            return {};
          }
        })
      );

      info.title = data.name;
      info.data = data;
      info.tracks = artist_tracks.filter((item) => item.SNG_ID);
      return info;
    default:
      throw 'Unknown spotify type!';
  }
};

module.exports = spotify2Deezer;
